package org.bhf.validation.annotations;

/**
 * Copyright (c) 2007, Blue Hole Software. All rights reserved.
 * Code licensed under the Apache 2.0 License:
 * http://www.apache.org/licenses/
 */

import org.bhf.i18n.ContextLocation;
import org.bhf.i18n.Message;
import org.bhf.i18n.MessageType;
import org.bhf.i18n.Messages;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;

/**
 * Test that the string is a valid date.
 * @see java.text.DateFormat
 */
@Documented
@Retention( RetentionPolicy.RUNTIME  )
@Target( ElementType.METHOD )
@Validator
public @interface Date
{
    static final String NONE = "";

    /**
     * @exclude
     */
    public static final class Validator
    {
        public static boolean validate( final Object value, final String ourKey, final Messages messages, final List<String> stack )
        {
            final Date that = ValidatorRegistry.lookup( ourKey, Date.class );

            if( parseDate( value.toString(), that.format(), that.lenient() ) != null )
                return true;

            Date.Validator.queueMessage( that, messages, stack );
            return false;
        }

        static java.util.Date parseDate( final String value, final String format, boolean lenient )
        {

            final DateFormat formatter;
            if( format != NONE )
            {
                formatter = new SimpleDateFormat( format );
            }
            else
            {
                formatter = DateFormat.getDateInstance(
                    DateFormat.SHORT, ContextLocation.getCurrentContextLocation().getLocale()
                );
            }

            formatter.setLenient( lenient );
            try
            {
                return formatter.parse( value );
            } catch( ParseException e ) {}

            return null;
        }

        private static void queueMessage( final Date that, final Messages messages, final List<String>stack )
        {
            messages.addMessage(
                new Message(
                    org.bhf.validation.Util.stackToPath( stack ), that.summary(), that.detail(),
                    MessageType.ERROR, that.bundle()
                )
            );
        }
    }

    /**
     * To be used in validating the date, otherwise the format associated with the <code>ContextLocation</code>
     * will be used.
     * @return Date format
     * @see java.text.DateFormat
     */
    String  format()    default NONE;

    /**
     * <code>true</code> if the format check should be lenient.
     * @return <code>true</code> if the format check should be lenient.
     * @see java.text.DateFormat
     */
    boolean lenient()   default true;

    /**
     * Override the default detail message. Generally, this is a key into a resource bundle.
     * @return The default detail message. Generally, this is a key into a resource bundle.
     */
    String  detail()    default "errors.date";

    /**
     * Override the default summary message. Generally, this is a key into a resource bundle.
     * @return The default summary message. Generally, this is a key into a resource bundle.
     */
    String  summary()   default "errors.date";

    /**
     * Override the default resource bundle.
     * @return The resource bundle.
     */
    String  bundle()    default "validation";
}
